<?php

namespace app\services;

use app\exceptions\SystemException;
use app\model\CustomerCreditCard;
use app\model\CustomerInfo;
use app\model\CustomerLoanAccount;
use think\Exception;
use think\facade\Log;

class CustomerService extends ApiService
{
    protected $customerInfo;
    protected $customerCreditCard;
    protected $customerLoanAccount;

    public function __construct(array $userInfo = [], array $params = [])
    {
        parent::__construct($userInfo, $params);
        $this->customerInfo = new CustomerInfo();
        $this->customerCreditCard = new CustomerCreditCard();
        $this->customerLoanAccount = new CustomerLoanAccount();
    }

    public function customerList()
    {
        $list = $this->customerInfo->customerList($this->params);
        $data = [];
        foreach ($list['data'] as $val) {
            $data[] = $val;
        }
        $list['data'] = $data;
        return $list;
    }

    public function customerInfo()
    {
        if (!$baseData = $this->customerInfo->customerInfo(intval($this->params['customer_id']))) {
            throw new SystemException('客户不存在');
        }
        $loanAccounts = $this->loanAccountList(intval($this->params['customer_id']));
        $baseData['non_cyclical'] = $loanAccounts['non_cyclical'];
        $baseData['cyclical_one'] = $loanAccounts['cyclical_one'];
        $baseData['cyclical_two'] = $loanAccounts['cyclical_two'];

        $baseData['credit_card'] = $this->creditCardList(intval($this->params['customer_id']));
        return $baseData;
    }

    public function createCustomer()
    {
        Log::error($this->params);
        $this->customerInfo->startTrans();
        try {
            //组装基本信息
            $customerId = $this->customerInfo->insertGetId($this->assembleInfo());

            //组装账户信息
            $loanAccounts = [];
            $this->assembleNonCyclical($loanAccounts, $customerId);
            $this->assembleCyclicalOne($loanAccounts, $customerId);
            $this->assembleCyclicalTwo($loanAccounts, $customerId);
            $this->customerLoanAccount->insertAll($loanAccounts);

            //组装信用卡信息
            if ($creditCard = $this->assembleCreditCard($customerId)) {
                $this->customerCreditCard->insertAll($creditCard);
            }
            $this->customerInfo->commit();
            return true;
        } catch (\Exception $e) {
            Log::error($e->getMessage() . $e->getTraceAsString());
            $this->customerInfo->rollback();
            throw new Exception('创建失败');
        }
    }

    public function saveCustomer()
    {
        $this->customerInfo->startTrans();
        try {
            $customerId = intval($this->params['customer_id']);
            //组装基本信息
            $this->customerInfo->modifyDataById($customerId, $this->assembleInfo());

            //组装账户信息
            $this->saveDealNonCyclical($customerId);
            $this->saveDealCyclicalOne($customerId);
            $this->saveDealCyclicalTwo($customerId);

            //组装信用卡信息
            $this->saveDealCreditCard($customerId);
            $this->customerInfo->commit();
            return true;
        } catch (\Exception $e) {
            Log::error($e->getMessage() . $e->getTraceAsString());
            $this->customerInfo->rollback();
            throw new Exception('创建失败');
        }
    }


    /**
     * @param int $userId
     * @return array[]
     */
    private function loanAccountList(int $customerId)
    {
        $data = ['non_cyclical' => [], 'cyclical_one' => [], 'cyclical_two' => []];
        $list = $this->customerLoanAccount->loanAccountList($customerId);
        if (!empty($data)) {
            $nonCyclical = $cyclicalOne = $cyclicalTwo = [];
            foreach ($list as $item) {
                if ($item['loan_type'] == 1) {
                    $nonCyclical[] = $item;
                } else if ($item['loan_type'] == 2) {
                    $cyclicalOne[] = $item;
                } else if ($item['loan_type'] == 3) {
                    $cyclicalTwo[] = $item;
                }
            };
            $data['non_cyclical'] = $nonCyclical;
            $data['cyclical_one'] = $cyclicalOne;
            $data['cyclical_two'] = $cyclicalTwo;
        }
        return $data;
    }

    private function creditCardList(int $customerId)
    {
        if (!$list = $this->customerCreditCard->creditCardList($customerId)) {
            return [];
        }
        return $list;
    }

    private function assembleInfo()
    {
        return [
            'username' => $this->params['username'],
            'organization_name' => $this->params['organization_name'],
            'organization_quality' => $this->params['organization_quality'],
            'birthday' => $this->params['birthday'],
            'birthday_day' => date('md', strtotime($this->params['birthday'])),
            'marriage' => $this->params['marriage'],
            'user_area' => $this->params['user_area'],
            'user_overdue' => $this->params['user_overdue'],
            'remark' => $this->params['remark'],
        ];
    }

    private function assembleNonCyclical(&$loanAccounts, int $customerId)
    {
        if (!empty($this->params['non_cyclical'])) {
            foreach ($this->params['non_cyclical'] as $item) {
                $loanAccounts[] = [
                    'customer_id' => $customerId,
                    'organization_name' => $item['organization_name'],
                    'start_time' => $item['start_time'],
                    'end_time' => $item['end_time'],
                    'total_amount' => $item['total_amount'],
                    'balance_amount' => $item['balance_amount'],
                    'repayment_style' => $item['repayment_style'],
                    'repayment_amount' => $item['repayment_amount'],
                    'repayment_day' => $item['repayment_day'],
                    'business_lines' => $item['business_lines'],
                    'guarantee_style' => $item['guarantee_style'],
                    'is_settle' => $item['is_settle'],
                    'settle_time' => $item['settle_time'],
                    'loan_type' => 1
                ];
            }
        }
        return true;
    }

    private function saveDealNonCyclical(int $customerId)
    {
        if (!empty($this->params['non_cyclical'])) {
            $loanAccounts = [];
            foreach ($this->params['non_cyclical'] as $item) {
                $id = intval($item['loan_account_id']);
                $data = [
                    'customer_id' => $customerId,
                    'organization_name' => $item['organization_name'],
                    'start_time' => $item['start_time'],
                    'end_time' => $item['end_time'],
                    'total_amount' => $item['total_amount'],
                    'balance_amount' => $item['balance_amount'],
                    'repayment_style' => $item['repayment_style'],
                    'repayment_amount' => $item['repayment_amount'],
                    'repayment_day' => $item['repayment_day'],
                    'business_lines' => $item['business_lines'],
                    'guarantee_style' => $item['guarantee_style'],
                    'is_settle' => $item['is_settle'],
                    'settle_time' => $item['settle_time'],
                    'loan_type' => 1
                ];
                if ($id != 0) {
                    $this->customerLoanAccount->modifyDataById($id, $data);
                } else {
                    $loanAccounts[] = $data;
                }
            }
            if ($loanAccounts) {
                $this->customerLoanAccount->insertAll($loanAccounts);
            }
        }
        return true;
    }


    private function assembleCyclicalOne(&$loanAccounts, int $customerId)
    {
        if (!empty($this->params['cyclical_one'])) {
            foreach ($this->params['cyclical_one'] as $item) {
                $loanAccounts[] = [
                    'customer_id' => $customerId,
                    'organization_name' => $item['organization_name'],
                    'start_time' => $item['start_time'],
                    'end_time' => $item['end_time'],
                    'total_amount' => $item['total_amount'],
                    'balance_amount' => $item['balance_amount'],
                    'repayment_style' => $item['repayment_style'],
                    'repayment_amount' => $item['repayment_amount'],
                    'repayment_day' => $item['repayment_day'],
                    'business_lines' => $item['business_lines'],
                    'guarantee_style' => $item['guarantee_style'],
                    'is_settle' => $item['is_settle'],
                    'settle_time' => $item['settle_time'],
                    'loan_type' => 2
                ];
            }
        }
        return true;
    }


    private function saveDealCyclicalOne(int $customerId)
    {
        if (!empty($this->params['cyclical_one'])) {
            $loanAccounts = [];
            foreach ($this->params['cyclical_one'] as $item) {
                $id = intval($item['loan_account_id']);
                $data = [
                    'customer_id' => $customerId,
                    'organization_name' => $item['organization_name'],
                    'start_time' => $item['start_time'],
                    'end_time' => $item['end_time'],
                    'total_amount' => $item['total_amount'],
                    'balance_amount' => $item['balance_amount'],
                    'repayment_style' => $item['repayment_style'],
                    'repayment_amount' => $item['repayment_amount'],
                    'repayment_day' => $item['repayment_day'],
                    'business_lines' => $item['business_lines'],
                    'guarantee_style' => $item['guarantee_style'],
                    'is_settle' => $item['is_settle'],
                    'settle_time' => $item['settle_time'],
                    'loan_type' => 2
                ];
                if ($id != 0) {
                    $this->customerLoanAccount->modifyDataById($id, $data);
                } else {
                    $loanAccounts[] = $data;
                }
            }
            if ($loanAccounts) {
                $this->customerLoanAccount->insertAll($loanAccounts);
            }
        }
        return true;
    }

    private function assembleCyclicalTwo(&$loanAccounts, int $customerId)
    {
        if (!empty($this->params['cyclical_two'])) {
            foreach ($this->params['cyclical_two'] as $item) {
                $loanAccounts[] = [
                    'customer_id' => $customerId,
                    'organization_name' => $item['organization_name'],
                    'start_time' => $item['start_time'],
                    'end_time' => $item['end_time'],
                    'total_amount' => $item['total_amount'],
                    'balance_amount' => $item['balance_amount'],
                    'repayment_style' => $item['repayment_style'],
                    'repayment_amount' => $item['repayment_amount'],
                    'repayment_day' => $item['repayment_day'],
                    'business_lines' => $item['business_lines'],
                    'guarantee_style' => $item['guarantee_style'],
                    'is_settle' => $item['is_settle'],
                    'settle_time' => $item['settle_time'],
                    'loan_type' => 3
                ];
            }
        }
        return true;
    }

    private function saveDealCyclicalTwo(int $customerId)
    {
        if (!empty($this->params['cyclical_two'])) {
            $loanAccounts = [];
            foreach ($this->params['cyclical_two'] as $item) {
                $id = intval($item['loan_account_id']);
                $data = [
                    'customer_id' => $customerId,
                    'organization_name' => $item['organization_name'],
                    'start_time' => $item['start_time'],
                    'end_time' => $item['end_time'],
                    'total_amount' => $item['total_amount'],
                    'balance_amount' => $item['balance_amount'],
                    'repayment_style' => $item['repayment_style'],
                    'repayment_amount' => $item['repayment_amount'],
                    'repayment_day' => $item['repayment_day'],
                    'business_lines' => $item['business_lines'],
                    'guarantee_style' => $item['guarantee_style'],
                    'is_settle' => $item['is_settle'],
                    'settle_time' => $item['settle_time'],
                    'loan_type' => 3
                ];
                if ($id != 0) {
                    $this->customerLoanAccount->modifyDataById($id, $data);
                } else {
                    $loanAccounts[] = $data;
                }
            }
            if ($loanAccounts) {
                $this->customerLoanAccount->insertAll($loanAccounts);
            }
        }
        return true;
    }

    public function assembleCreditCard(int $customerId)
    {
        $creditCard = [];
        if (!empty($this->params['credit_card'])) {
            foreach ($this->params['credit_card'] as $item) {
                $creditCard[] = [
                    'customer_id' => $customerId,
                    'organization_name' => $item['organization_name'],
                    'open_time' => $item['open_time'],
                    'total_amount' => $item['total_amount'],
                    'bill_day' => $item['bill_day'],
                    'is_logout' => $item['is_logout']
                ];
            }
        }
        return $creditCard;
    }

    public function saveDealCreditCard(int $customerId)
    {
        if (!empty($this->params['credit_card'])) {
            $creditCard = [];
            foreach ($this->params['credit_card'] as $item) {
                $id = intval($item['credit_card_id']);
                $data = [
                    'customer_id' => $customerId,
                    'organization_name' => $item['organization_name'],
                    'open_time' => $item['open_time'],
                    'total_amount' => $item['total_amount'],
                    'bill_day' => $item['bill_day'],
                    'is_logout' => $item['is_logout']
                ];
                if ($id != 0) {
                    $this->customerCreditCard->modifyDataById($id, $data);
                } else {
                    $creditCard[] = $data;
                }
            }
            if ($creditCard) {
                $this->customerCreditCard->insertAll($creditCard);
            }
        }
        return true;
    }
}